//
//  CYCommunication.m
//  cyjf
//
//  Created by tauCross on 2017/5/10.
//  Copyright © 2017年 Auto Financing. All rights reserved.
//

#import "CYCommunication.h"

#import "CYAuthManager.h"

#import <CommonCrypto/CommonCryptor.h>
#import <TCJSONKit.h>
#import <CocoaSecurity.h>




@interface CYCommunication ()

@property(nonatomic, strong)UIAlertController *safeAlert;

@end


@implementation CYCommunication

+ (instancetype)standardCommunication
{
    static CYCommunication *communication = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
#ifdef CYJF_DEV
        NSString *baseURL = SAFE_STRING(CY_MainBundle_InfoDictionaryValue(@"dev_base_url"));
        if(baseURL.length == 0 || baseURL.tc_url == nil)
        {
            baseURL = CY_API_BASE_URL;
        }
#else
        NSString *baseURL = CY_API_BASE_URL;
#endif
        communication = [[CYCommunication alloc] initWithBaseURL:baseURL.tc_url];
#ifdef CYJF_API_SSL
        NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"cyjf_ssl" ofType:@"cer"];
        NSData *cerData = [NSData dataWithContentsOfFile:cerPath];
        AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
        securityPolicy.allowInvalidCertificates = NO;
        securityPolicy.pinnedCertificates = [NSSet setWithObject:cerData];
        securityPolicy.validatesDomainName = YES;
        communication.securityPolicy = securityPolicy;
#endif
    });
    return communication;
}

- (void)requestWithUrl:(NSString *)url parameters:(NSMutableDictionary *)parameters encrypt:(BOOL)encrypt complete:(void (^)(NSString *))complete
{
    @weakify(self);
    [self POST:encrypt ? [self signUrlWithUrl:url] : url parameters:encrypt ? [self encryptWithParameters:parameters] : parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        @strongify(self);
        if([responseObject isKindOfClass:[NSDictionary class]])
        {
            NSString *isEnc = responseObject[@"isEnc"];
            NSString *resText = responseObject[@"resText"];
            if([isEnc isKindOfClass:[NSString class]] && [resText isKindOfClass:[NSString class]])
            {
                NSString *originalString = nil;
                if([isEnc isEqualToString:@"Y"])
                {
                    originalString = [resText cy_desDecrypt];
                }
                else
                {
                    originalString = resText;
                }
                [self logWithTask:task response:originalString requestUrl:url requestParameters:parameters];
                if(complete)
                {
                    complete(originalString);
                }
                return;
            }
            [self logWithTask:task response:[responseObject tc_JSONString] requestUrl:url requestParameters:parameters];
            if(complete)
            {
                complete([responseObject tc_JSONString]);
                return;
            }
        }
        if(complete)
        {
            complete(@{@"code":@"-1", @"errorMsg":@"请求失败"}.tc_JSONString);
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        @strongify(self);
        [self logFaildWithTask:task error:error requestUrl:url requestParameters:parameters];
        NSString *msg = @"请求失败";
        if([error.userInfo[@"NSLocalizedDescription"] rangeOfString:@"Request failed: internal server error (500)"].location != NSNotFound)
        {
            msg = @"系统错误";
        }
        complete(@{@"code":@"-2", @"errorMsg":msg}.tc_JSONString);
        if(error.code == -999 && [task.originalRequest.URL.absoluteString hasPrefix:CY_API_BASE_URL] && self.safeAlert == nil)
        {
            [SVProgressHUD dismiss];
            self.safeAlert = [UIAlertController alertControllerWithTitle:@"警告" message:@"当前网络环境不安全，请更换网络（使用3G、4G等）后再进行相应操作！" preferredStyle:UIAlertControllerStyleAlert];
            [self.safeAlert addAction:[UIAlertAction actionWithTitle:@"" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
                @strongify(self);
                self.safeAlert = nil;
            }]];
            [[[[UIApplication sharedApplication] delegate] window].rootViewController presentViewController:self.safeAlert animated:YES completion:nil];
        }
    }];
}

#pragma mark - Private Method
- (void)logWithTask:(NSURLSessionDataTask *)task response:(id)response requestUrl:(NSString *)url requestParameters:(NSDictionary *)parameters
{
    DLog(@"\n\nRequest:\nURL:\n%@\n\nBODY:\n%@\n\n\n\nResponse:\n%@\n\n\n\n\n", task.originalRequest.URL, [[NSString alloc] initWithData:task.originalRequest.HTTPBody encoding:NSUTF8StringEncoding], response);
}

- (void)logFaildWithTask:(NSURLSessionDataTask *)task error:(NSError *)error requestUrl:(NSString *)url requestParameters:(NSDictionary *)parameters
{
    DLog(@"\n\nRequest:\nURL:\n%@\n\nBODY:\n%@\n\n\n\nError:\n%@\n\n\n\n\n", task.originalRequest.URL, [[NSString alloc] initWithData:task.originalRequest.HTTPBody encoding:NSUTF8StringEncoding], error);
}

- (NSDictionary *)encryptWithParameters:(NSDictionary *)parameters 
{
    NSMutableArray *parts = [NSMutableArray array];
    for (NSString *key in [parameters allKeys]) {
        NSString *part = [NSString stringWithFormat:@"%@=%@", key, [parameters valueForKey:key]];
        [parts addObject: part];
    }
    NSString *partString = [parts componentsJoinedByString:@"&"];
    NSData *data = [partString dataUsingEncoding:NSUTF8StringEncoding];
    char keyPtr[kCCKeySizeAES128];
    bzero(keyPtr, sizeof(keyPtr));
    [@"8F&*663#" getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
    NSData *keyData = [NSData dataWithBytes:keyPtr length:sizeof(keyPtr)];
    NSData *viData = [NSData dataWithBytes:"0102030405060708" length:16];
    NSString *key = [CocoaSecurity aesEncryptWithData:data key:keyData iv:viData].base64;
    return @{@"key" : key};
}

- (NSString *)signUrlWithUrl:(NSString *)url
{
    NSString *times = [NSString stringWithFormat:@"%llu", (long long)([[NSDate date] timeIntervalSince1970] * 1000)];
    NSString *random = [NSUUID UUID].UUIDString;
    NSString *loginToken = @"bankcar-vMUaZj5cUDV85aqR";
    NSString *appId = @"vMUaZj5cUDV85aqR";
    NSArray *secretArr = @[times, random, loginToken,appId];
    NSArray *reversedArray = [secretArr sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
        NSComparisonResult result = [obj1 compare:obj2];
        return result == NSOrderedAscending;
    }];
    NSString *secretStr = [reversedArray componentsJoinedByString:@""];
    NSString *sign = secretStr.tc_sha1;
    return [NSString stringWithFormat:@"%@?sign=%@&times=%@&random=%@", url, sign, times, random];
}

@end
